home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / mac / developm / source / divaplug.cpt / VideoShop Plug-In Kit 1.0 / SampleFilt.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-04-30  |  13.8 KB  |  549 lines

  1. /*
  2.  
  3.     SampleFilt.c
  4.     
  5.     Sample Filter Effect for DiVA VideoShop
  6.     
  7.     04/28/92    Ivçn Cavero Bela£nde
  8.     
  9.  
  10. */
  11.  
  12. #include <Types.h>
  13. #include <Memory.h>
  14. #include <Resources.h>
  15. #include <QuickDraw.h>
  16. #include <QDOffscreen.h>
  17. #include <Dialogs.h>
  18. #include <OSUtils.h>
  19. #include <Packages.h>
  20. #include <Errors.h>
  21. #include <ToolUtils.h>
  22. #include <SysEqu.h>
  23. #include <Math.h>
  24. #include <GestaltEqu.h>
  25. #include "DiVAFilter.h"
  26.  
  27. /*    Konstants    */
  28.  
  29. /*    Shades of gray for 3-D objects    */
  30. #define kLightGray    0xffff
  31. #define kMediumGray    0xdddd
  32. #define kDarkGray    0xaaaa
  33.  
  34. /*    Dialog konstants    */
  35. #define dialogID            16001
  36. #define defaultItem            3
  37. #define    intensityItem        5
  38. #define dividerLinesItem    7
  39. #define    imageItem            9
  40. #define frameItem            10
  41. #define    forwardItem            11
  42. #define    backwardItem        12
  43.  
  44. /*    Type Definitions    */
  45.  
  46. typedef struct Params {
  47.     short    filterIntensity;
  48.     Boolean    backward;    //    defaults to false (end pixellated)
  49.     FiltParamPtr    filterParamBlock;    //    Ptr to paramblock for use of custom ditems.
  50. }    Params, **ParamsHandle;
  51.  
  52. /*    Prototypes    */
  53.  
  54. FiltErr DoParameters (FiltParamPtr params);
  55.  
  56. FiltErr DoProcessFrame (FiltParamPtr params, short currentStep, short totalSteps);
  57.  
  58. void    DoFilter (PixMapHandle src, GWorldPtr destGW, short current,
  59.     short total, short intensity);
  60.  
  61.  
  62. pascal FiltErr FilterEntryPoint (short selector, FiltParamPtr params, long *data,
  63.     short currentStep, short totalSteps)
  64. /*    The entry point for the filter module. Conforms to     */
  65. {
  66. #pragma unused(data)
  67.     /* If first call, allocate and initialize our globals */
  68.     switch (selector) {
  69.         case FiltParameters:
  70.             return (DoParameters (params));
  71.             break;
  72.         case FiltPrepare:
  73.         case FiltStart:
  74.         case FiltFinish:
  75.             return (noErr);
  76.             break;
  77.         case FiltProcessFrame:
  78.             return (DoProcessFrame (params,currentStep,totalSteps));
  79.             break;
  80.         default:
  81.             return (-1);
  82.     }
  83. }
  84.  
  85. pascal Boolean DoTestAbort (ProcPtr codeAddress)
  86. /*    Inline code to call the TestAbort function    */
  87.     =     {0x205F,            //    move.l    (a7)+,a0        pop procPtr from stack
  88.          0x4E90};            //    jsr        (a0)            and call it
  89.  
  90. Boolean TestAbort (FiltParamPtr params)
  91. {
  92.     ProcPtr address;
  93.  
  94.     address = params->abortProc;
  95.     return (DoTestAbort (address));
  96. }
  97.  
  98. pascal void DoUpdateProgress (long done, long total, ProcPtr codeAddress)
  99. /*    Inline code to call the UpdateProgress function    */
  100.     =     {0x205F,            //    move.l    (a7)+,a0        pop procPtr from stack
  101.          0x4E90};            //    jsr        (a0)            and call it
  102.  
  103. void UpdateProgress (FiltParamPtr params, long done, long total)
  104. {
  105.     ProcPtr address;
  106.  
  107.     address = params->progressProc;
  108.     DoUpdateProgress (done, total, address);
  109. }
  110.  
  111. void CenterDialogBestDevice (DialogTHndl dt)
  112. /*
  113.     Given a dialog template in dt, modify it so as to center the dialog on the
  114.     best (deepest) device.    Used to place options dialog (with image preview)
  115.     in that device.
  116. */
  117. {
  118.     short width;
  119.     short height;
  120.     GDHandle    maxDevice;
  121.     RgnHandle    grayRgn = GetGrayRgn();
  122.     Rect    r = (**grayRgn).rgnBBox,dr;
  123.     
  124.     maxDevice = GetMaxDevice(&r);
  125.     r = (**maxDevice).gdRect;
  126.     width  = r.right - r.left;
  127.     height = r.bottom - r.top;
  128.     
  129.     dr = (**dt).boundsRect;
  130.     OffsetRect (&dr, r.left-dr.left, r.top-dr.top);
  131.     OffsetRect (&dr, (width - (dr.right-dr.left)) / 2,
  132.                     (height - (dr.bottom-dr.top) - GetMBarHeight()) / 3 + GetMBarHeight());
  133.     (**dt).boundsRect = dr;
  134. }
  135.  
  136. GDHandle    GetWindowGDevice(WindowPtr w)
  137. /*
  138.     Find the deepest gdevice the window intersects. Used for determining the depth
  139.     of the screen we're drawing on (to look good on B/W displays).
  140. */
  141. {
  142.     Rect    r=w->portRect;
  143.     GrafPtr    oldPort;
  144.     GDHandle    theGD;
  145.     
  146.     GetPort (&oldPort);
  147.     SetPort (w);
  148.     LocalToGlobal((Point *)&r);
  149.     LocalToGlobal((Point *)(&(r.bottom)));
  150.     theGD = GetMaxDevice(&r);
  151.     SetPort (oldPort);
  152.     return (theGD);
  153. }
  154.  
  155. pascal void DrawLines (DialogPtr theDialog, short itemNo)
  156. /*
  157.     userItem drawing routine for dividing lines (with shadow)
  158. */
  159. {
  160.     RGBColor    oldColor,greyColor;
  161.     short    itemType;
  162.     Handle    me;
  163.     Rect    box;
  164.     
  165.     GetDItem(theDialog,itemNo,&itemType,&me,&box);
  166.     GetForeColor(&oldColor);
  167.     RGBForeColor((RGBColor*)RGBBlack);
  168.     MoveTo(box.left,box.top);
  169.     LineTo(box.right-2,box.top);
  170.     MoveTo(box.left,box.top+3);
  171.     LineTo(box.right-2,box.top+3);
  172.     if (((**((*GetWindowGDevice(theDialog))->gdPMap)).pixelSize >= 8)) {
  173.         greyColor.red = greyColor.green = greyColor.blue = 0x7777;
  174.         RGBForeColor (&greyColor);
  175.         MoveTo(box.left+1,box.top+1);
  176.         LineTo(box.right-1,box.top+1);
  177.         MoveTo(box.left+1,box.top+4);
  178.         LineTo(box.right-1,box.top+4);
  179.     }
  180.     RGBForeColor(&oldColor);
  181. }
  182.  
  183. pascal void OutlineOK (DialogPtr dp, short item)
  184. /*
  185.     userItem drawing routine for outlining the default button in the dialog box
  186. */
  187. {
  188.     Rect r;
  189.     Handle h;
  190.     short itemType;
  191.  
  192.     item = ok;
  193.     GetDItem (dp, item, &itemType, &h, &r);
  194.     PenNormal ();
  195.     PenSize (3, 3);
  196.     InsetRect (&r, -4, -4);
  197.     FrameRoundRect (&r, 16, 16);
  198.     PenNormal ();
  199. }
  200.  
  201. pascal void DrawSunkFrame (DialogPtr dp, short item)
  202. /*
  203.     User item drawing routine for drawing the 3-D-like frame for the preview image.
  204. */
  205. {
  206.     Rect    r;
  207.     Handle    h;
  208.     short    itemType;
  209.     RGBColor    darkGray, lightGray;
  210.     RGBColor    oldForeColor;
  211.     Boolean    bwMode = (((**((*GetWindowGDevice(dp))->gdPMap)).pixelSize < 8));
  212.     
  213.     GetDItem (dp, item, &itemType, &h, &r);
  214.     darkGray.red = darkGray.green = darkGray.blue = kDarkGray;
  215.     lightGray.red = lightGray.green = lightGray.blue = kLightGray;
  216.     GetForeColor(&oldForeColor);
  217.     if (!bwMode) {
  218.         RGBForeColor(&darkGray);
  219.         MoveTo(r.left,r.bottom-1);
  220.         LineTo(r.left,r.top);
  221.         LineTo(r.right-1,r.top);
  222.     } else RGBForeColor((RGBColor*)RGBBlack);
  223.     MoveTo(r.left+1,r.bottom-2);
  224.     LineTo(r.left+1,r.top+1);
  225.     LineTo(r.right-2,r.top+1);
  226.     if (!bwMode) {
  227.         RGBForeColor(&lightGray);
  228.         MoveTo(r.right-1,r.top+1);
  229.         LineTo(r.right-1,r.bottom-1);
  230.         LineTo(r.left,r.bottom-1);
  231.     } else RGBForeColor((RGBColor*)RGBBlack);
  232.     MoveTo(r.right-2,r.top+2);
  233.     LineTo(r.right-2,r.bottom-2);
  234.     LineTo(r.left+1,r.bottom-2);
  235.     InsetRect(&r,2,2);
  236.     RGBForeColor((RGBColor*)RGBBlack);
  237.     FrameRect(&r);
  238.     RGBForeColor(&oldForeColor);
  239. }
  240.  
  241. void    RectLocalToGlobal (Rect *theRect)
  242. {
  243.     LocalToGlobal((Point *)theRect);
  244.     LocalToGlobal((Point *)(&(theRect->bottom)));
  245. }
  246.  
  247. pascal void    DrawFilteredImage (DialogPtr dp, short item)
  248. /*
  249.     User item drawing routine to draw the preview image
  250. */
  251. {
  252.     Rect    r;
  253.     Handle    h;
  254.     short    itemType;
  255.     GDHandle    oldGD,destGD = GetWindowGDevice(dp);
  256.     ParamsHandle    theParams = (ParamsHandle)GetWRefCon(dp);
  257.     FiltParamPtr    params = (**theParams).filterParamBlock;
  258.     unsigned char    oldState;
  259.     PixMapHandle    filtered;
  260.     RGBColor    oldFore,oldBack;
  261.     
  262.     if (*((short*)SysVersion)<0x700) {
  263.         filtered = params->destImage->portPixMap;
  264.     } else {
  265.         filtered = GetGWorldPixMap (params->destImage);
  266.     }
  267.     GetDItem (dp, item, &itemType, &h, &r);
  268.     oldGD = GetGDevice();
  269.     SetGDevice (destGD);
  270.     GetForeColor (&oldFore);
  271.     GetBackColor (&oldBack);
  272.     RGBForeColor ((RGBColor*)RGBBlack);
  273.     RGBBackColor ((RGBColor*)RGBWhite);
  274.     oldState = HGetState ((Handle)((CGrafPtr)dp)->portPixMap);
  275.     HLock ((Handle)((CGrafPtr)dp)->portPixMap);
  276.     CopyBits((BitMap*)*filtered,&(dp->portBits),&((**filtered).bounds),&r,srcCopy,nil);
  277.     HSetState ((Handle)((CGrafPtr)dp)->portPixMap,oldState);
  278.     RGBForeColor (&oldFore);
  279.     RGBBackColor (&oldBack);
  280.     SetGDevice (oldGD);
  281. }
  282.  
  283. pascal void    UpdateImage (ControlHandle ctrl, short *value)
  284. /*
  285.     Callback routine for the control to update the preview image. Gets called by
  286.     VideoShop's slider control definition while the control is being dragged.
  287. */
  288. {
  289.     DialogPtr    dp = (**ctrl).contrlOwner;
  290.     ParamsHandle    theParams = (ParamsHandle)GetWRefCon(dp);
  291.         /*    Get the parameters handle from the window's refcon    */
  292.     FiltParamPtr    params = (**theParams).filterParamBlock;
  293.         /*    Get the parameter block we stuffed there    */
  294.     PixMapHandle    src = params->srcImage;
  295.     GrafPtr    oldPort;
  296.     
  297.     (**theParams).filterIntensity = *value;
  298.     DoFilter (src, params->destImage, 100, 100, (**theParams).filterIntensity);
  299.     GetPort (&oldPort);
  300.     SetPort (dp);
  301.     DrawFilteredImage (dp,imageItem);
  302.     SetPort (oldPort);
  303. }
  304.  
  305. void    SetupDItems (DialogPtr dp)
  306. /*
  307.     Set up the dialog items
  308. */
  309. {
  310.     short    itemType;
  311.     Handle    h;
  312.     Rect    r;
  313.     
  314.     /*    Point default useritem to default button outline routine    */
  315.     GetDItem (dp, defaultItem, &itemType, &h                  , &r);
  316.     SetDItem (dp, defaultItem,  itemType, (Handle) &OutlineOK, &r);
  317.     
  318.     /*    Point divider lines useritem to dividing lines drawing routine    */
  319.     GetDItem (dp, dividerLinesItem, &itemType, &h                  , &r);
  320.     SetDItem (dp, dividerLinesItem,  itemType, (Handle) DrawLines, &r);    
  321.     
  322.     /*    Point preview image item to image blitting routine    */
  323.     GetDItem (dp, imageItem, &itemType, &h                  , &r);
  324.     SetDItem (dp, imageItem,  itemType, (Handle) &DrawFilteredImage, &r);
  325.     
  326.     /*    Point preview image frame item to drawing routine    */
  327.     GetDItem (dp, frameItem, &itemType, &h                  , &r);
  328.     SetDItem (dp, frameItem,  itemType, (Handle) &DrawSunkFrame, &r);
  329.     
  330.     /*    Point control's refCon to the the dragging callback routine    */
  331.     GetDItem (dp, intensityItem, &itemType, &h, &r);
  332.     SetCRefCon((ControlHandle)h,(long)UpdateImage);
  333. }
  334.  
  335. void    RecalcDItems (ParamsHandle p, DialogPtr dp)
  336. {
  337.     short    itemType;
  338.     ControlHandle    ctrl;
  339.     Rect    r;
  340.     
  341.     GetDItem (dp, intensityItem, &itemType, (Handle*)&ctrl, &r);
  342.     (**p).filterIntensity = GetCtlValue(ctrl);
  343.     
  344.     GetDItem (dp, forwardItem, &itemType, (Handle*)&ctrl, &r);
  345.     SetCtlValue(ctrl,1-(**p).backward);
  346.     GetDItem (dp, backwardItem, &itemType, (Handle*)&ctrl, &r);
  347.     SetCtlValue(ctrl,(**p).backward);
  348. }
  349.  
  350. FiltErr DoParameters (FiltParamPtr params)
  351. /*
  352.     Prompt the user for parameters if necessary.
  353. */
  354. {
  355.     DialogPtr dp;
  356.     DialogTHndl dt;
  357.     ParamsHandle    theParams;
  358.     short    item;
  359.     GrafPtr    oldPort;
  360.     GWorldFlags    pmStateSrc,pmStateDest;
  361.     unsigned char    stateSrc,stateDest;
  362.     PixMapHandle    src,dest;
  363.     
  364.     /*    If we didn't get passed a params handle, allocate and initialize it    */
  365.     if (!params->parameters) {
  366.         theParams = (ParamsHandle)NewHandleClear(sizeof(Params));
  367.         if (!theParams) return (FiltErrOutOfMemory|MemError());
  368.         (**theParams).filterIntensity = 80;
  369.     } else
  370.     /*
  371.         Otherwise, we just return. If we required specific hardware or mounds of
  372.         memory we would check here.
  373.     */
  374.         return (noErr);
  375.     
  376.     src = params->srcImage;
  377.     
  378.     /*    Prepare for previewing filter    */
  379.     
  380.     /*    Get the image pixmaps, dealing with pre-System 7 GetGWorldPixMap bug    */
  381.     if (*((short*)SysVersion)<0x700) {
  382.         dest = params->destImage->portPixMap;
  383.     } else {
  384.         dest = GetGWorldPixMap (params->destImage);
  385.     }
  386.     
  387.     /*    Save pixmaps' state and lock the buffers    */
  388.     pmStateSrc = GetPixelsState(src);
  389.     LockPixels (src);
  390.     stateSrc = HGetState ((Handle)src);
  391.     MoveHHi ((Handle)src);
  392.     HLock ((Handle)src);
  393.     pmStateDest = GetPixelsState(dest);
  394.     LockPixels (dest);
  395.     stateDest = HGetState ((Handle)dest);
  396.     MoveHHi ((Handle)dest);
  397.     HLock ((Handle)dest);
  398.     
  399.     (**theParams).filterParamBlock = params;
  400.     
  401.     /*    Load in the dialog and reposition it in the best device    */
  402.     dt = (DialogTHndl) GetResource ('DLOG', dialogID);
  403.     HNoPurge ((Handle) dt);
  404.     CenterDialogBestDevice (dt);
  405.     
  406.     /*    Show it    */
  407.     dp = GetNewDialog (dialogID, nil, (WindowPtr) -1);
  408.     GetPort (&oldPort);
  409.     SetPort (dp);
  410.     
  411.     /*    Save our params handle in the window refcon for the user items    */
  412.     SetWRefCon(dp,(long)theParams);
  413.     
  414.     /*    Setup the user items and initialize all controls to initial state    */
  415.     SetupDItems(dp);
  416.     RecalcDItems(theParams,dp);
  417.     
  418.     DoFilter (src, params->destImage, 100, 100, (**theParams).filterIntensity);
  419.     
  420.     do {
  421.         ModalDialog (nil, &item);
  422.         switch (item) {
  423.             case forwardItem:
  424.                 (**theParams).backward=false;
  425.                 RecalcDItems(theParams,dp);
  426.                 break;
  427.             case backwardItem:
  428.                 (**theParams).backward=true;
  429.                 RecalcDItems(theParams,dp);
  430.                 break;
  431.             default:
  432.                 break;
  433.         }
  434.     } while (item != ok && item != cancel);
  435.     
  436.     SetPort (oldPort);
  437.     DisposDialog (dp);
  438.     HPurge ((Handle) dt);
  439.     
  440.     /*    Restore pixel maps state    */
  441.     HSetState ((Handle)src,stateSrc);
  442.     SetPixelsState(src,pmStateSrc);
  443.     HSetState ((Handle)dest,stateDest);
  444.     SetPixelsState(dest,pmStateDest);
  445.  
  446.     if (item == cancel) {
  447.         DisposHandle((Handle)theParams);
  448.         params->parameters = nil;
  449.         return (FiltErrReported);
  450.     }
  451.     params->parameters=(Handle)theParams;
  452.     return (noErr);
  453. }
  454.  
  455. void    DoFilter (PixMapHandle src, GWorldPtr destGW, short current,
  456.     short total, short intensity)
  457. /*    Perform the filtering operation    */
  458. {
  459. #pragma unused(current,total,intensity,newRect)
  460.     Rect    r = (**src).bounds,newRect;
  461.     RGBColor    oldFore,oldBack;
  462.     GWorldPtr    oldGW;
  463.     PixMapHandle    dest;
  464.     GDHandle    oldGD;
  465.     
  466.     /*    Check for pre-System 7 QD bug (GetGWorldPixMap didn't work)    */
  467.     
  468.     if (*((short*)SysVersion)<0x700) {
  469.         dest = destGW->portPixMap;
  470.     } else {
  471.         dest = GetGWorldPixMap (destGW);
  472.     }
  473.     
  474.     /*    Save state    */
  475.     
  476.     GetGWorld (&oldGW,&oldGD);
  477.     SetGWorld (destGW,GetGWorldDevice(destGW));
  478.     GetForeColor (&oldFore);
  479.     GetBackColor (&oldBack);
  480.     RGBForeColor ((RGBColor*)RGBBlack);
  481.     RGBBackColor ((RGBColor*)RGBWhite);
  482.     
  483.     /* perform filter */
  484.     
  485.     CopyBits((BitMap*)*src,(BitMap*)*dest,&r,&r,srcCopy,nil);
  486.     
  487.     /*    Wait for accelerators    */
  488.     while (!(QDDone((GrafPtr)destGW)));
  489.     
  490.     /*    Restore state    */
  491.     
  492.     RGBForeColor (&oldFore);
  493.     RGBBackColor (&oldBack);
  494.     SetGWorld(oldGW,oldGD);
  495. }
  496.  
  497. FiltErr DoProcessFrame (FiltParamPtr params, short currentStep, short totalSteps)
  498. {
  499.     GWorldFlags    pmStateSrc,pmStateDest;
  500.     GWorldPtr    destGW;
  501.     PixMapHandle    src,dest;
  502.     unsigned char    stateSrc,stateDest;
  503.     ParamsHandle    p = (ParamsHandle)params->parameters;
  504.     
  505.     if (TestAbort (params)) return (FiltErrReported);
  506.     
  507.     src = params->srcImage;
  508.     destGW = params->destImage;
  509.     
  510.     /*    Check for pre-System 7 QD bug (GetGWorldPixMap didn't work)    */
  511.     if (*((short*)SysVersion)<0x700) {
  512.         dest = destGW->portPixMap;
  513.     } else {
  514.         dest = GetGWorldPixMap (destGW);
  515.     }
  516.     
  517.     /*    Spin the wheel    */
  518.     UpdateProgress (params,0,2);
  519.     
  520.     /* save offscreen pixels state and lock them down for drawing */
  521.     pmStateSrc = GetPixelsState(src);
  522.     LockPixels (src);
  523.     stateSrc = HGetState ((Handle)src);
  524.     MoveHHi ((Handle)src);
  525.     HLock ((Handle)src);
  526.     
  527.     pmStateDest = GetPixelsState(dest);
  528.     LockPixels (dest);
  529.     stateDest = HGetState ((Handle)dest);
  530.     MoveHHi ((Handle)dest);
  531.     HLock ((Handle)dest);
  532.         
  533.     /* perform filter    */
  534.     if ((**p).backward) {
  535.         DoFilter (src,destGW,totalSteps-currentStep,totalSteps,(**p).filterIntensity);
  536.     } else {
  537.         DoFilter (src,destGW,currentStep,totalSteps,(**p).filterIntensity);
  538.     }
  539.     
  540.     UpdateProgress (params,2,2);
  541.  
  542.     HSetState ((Handle)src,stateSrc);
  543.     SetPixelsState(src,pmStateSrc);
  544.     HSetState ((Handle)dest,stateDest);
  545.     SetPixelsState(dest,pmStateDest);
  546.     
  547.     return (noErr);
  548. }
  549.